home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / VBSamples / Common / d3dPick.cls < prev    next >
Text File  |  2001-10-08  |  11KB  |  335 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "CD3DPick"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14.  
  15. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  16. '
  17. '  Copyright (C) 1999-2001 Microsoft Corporation.  All Rights Reserved.
  18. '
  19. '  File:       D3DPick.cls
  20. '  Content:    D3D Visual Basic Framework Pick object
  21. '              See raypack and viewport pick entrypoints
  22. '
  23. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  24.  
  25. Option Explicit
  26.  
  27. Dim m_item() As D3D_PICK_RECORD
  28. Dim m_frame() As CD3DFrame
  29. Dim m_mesh() As CD3DMesh
  30. Dim m_count As Long
  31. Dim m_maxsize As Long
  32. Const kGrowSize = 10
  33.  
  34. '-----------------------------------------------------------------------------
  35. ' Name: GetCount
  36. ' Dest: returns number of items picked
  37. '-----------------------------------------------------------------------------
  38. Public Function GetCount() As Long
  39.     GetCount = m_count
  40. End Function
  41.  
  42. '-----------------------------------------------------------------------------
  43. ' Name: GetRecord
  44. ' Desc: returns the properties of a given pick item
  45. '-----------------------------------------------------------------------------
  46. Public Sub GetRecord(i As Long, ByRef a As Single, ByRef b As Single, ByRef dist As Single, ByRef triFaceid As Long)
  47.     a = m_item(i).a
  48.     b = m_item(i).b
  49.     dist = m_item(i).dist
  50.     triFaceid = m_item(i).triFaceid
  51. End Sub
  52.  
  53. '-----------------------------------------------------------------------------
  54. ' Name: GetFrame
  55. ' Desc: returns the frame of a given pick item
  56. '-----------------------------------------------------------------------------
  57. Public Function GetFrame(i As Long) As CD3DFrame
  58.     Set GetFrame = m_frame(i)
  59. End Function
  60.  
  61. '-----------------------------------------------------------------------------
  62. ' Name: GetMesh
  63. ' Desc: returns the mesh of a given pick item
  64. '-----------------------------------------------------------------------------
  65. Public Function GetMesh(i As Long) As CD3DMesh
  66.     Set GetMesh = m_mesh(i)
  67. End Function
  68.  
  69. '-----------------------------------------------------------------------------
  70. ' Name: FindNearest
  71. ' Desc: returns the index of the pick with the smallest distance (closest to viewer)
  72. '-----------------------------------------------------------------------------
  73. Public Function FindNearest() As Long
  74.     Dim q As Long, mindist As Single, i As Long
  75.     q = -1
  76.     mindist = 1E+38
  77.     For i = 0 To m_count - 1
  78.         If m_item(i).dist < mindist Then
  79.             q = i
  80.             mindist = m_item(i).dist
  81.         End If
  82.     Next
  83.     FindNearest = q
  84. End Function
  85.  
  86.  
  87. '-----------------------------------------------------------------------------
  88. ' Name: FindFurthest
  89. ' Desc: returns the index of the pick with the largest distance
  90. '-----------------------------------------------------------------------------
  91. Public Function FindFurthest() As Long
  92.     Dim q As Long, maxdist As Single, i As Long
  93.     q = -1
  94.     maxdist = -1E+38
  95.     For i = 0 To m_count - 1
  96.         If m_item(i).dist < maxdist Then
  97.             q = i
  98.             maxdist = m_item(i).dist
  99.         End If
  100.     Next
  101.     FindFurthest = q
  102. End Function
  103.  
  104.  
  105. '-----------------------------------------------------------------------------
  106. ' Name: Destroy
  107. ' Desc: Release all references
  108. '-----------------------------------------------------------------------------
  109. Public Function Destroy()
  110.     ReDim m_mesh(0)
  111.     ReDim m_frame(0)
  112.     m_count = 0
  113.     m_maxsize = 0
  114.     
  115. End Function
  116.  
  117.  
  118. '-----------------------------------------------------------------------------
  119. ' Name: ViewportPick
  120. ' Params:
  121. '    frame      parent of frame heirarchy to pick from
  122. '    x          x screen coordinate in pixels
  123. '    y          y screen coordinate in pixels
  124. '
  125. ' Note: After call GetCount to see if any objets where hit
  126. '-----------------------------------------------------------------------------
  127. Public Function ViewportPick(frame As CD3DFrame, x As Single, y As Single)
  128.     Destroy
  129.     
  130.     Dim viewport As D3DVIEWPORT8
  131.     Dim world As D3DMATRIX
  132.     Dim proj As D3DMATRIX
  133.     Dim view As D3DMATRIX
  134.     
  135.     'NOTE the following functions will fail on PURE HAL devices
  136.     'use ViewportPickEx if working with pureHal devices
  137.     
  138.     g_dev.GetViewport viewport
  139.     world = g_identityMatrix
  140.     g_dev.GetTransform D3DTS_VIEW, view
  141.     g_dev.GetTransform D3DTS_PROJECTION, proj
  142.     
  143.     ViewportPick = ViewportPickEx(frame, viewport, proj, view, world, x, y)
  144.     
  145. End Function
  146.  
  147. '-----------------------------------------------------------------------------
  148. ' Name: ViewportPickEx
  149. ' Desc: Aux function for ViewportPick
  150. '-----------------------------------------------------------------------------
  151. Public Function ViewportPickEx(frame As CD3DFrame, viewport As D3DVIEWPORT8, proj As D3DMATRIX, view As D3DMATRIX, world As D3DMATRIX, x As Single, y As Single) As Boolean
  152.     
  153.     If frame.Enabled = False Then Exit Function
  154.     
  155.     Dim vIn As D3DVECTOR, vNear As D3DVECTOR, vFar As D3DVECTOR, vDir As D3DVECTOR
  156.     Dim bHit As Boolean, i As Long
  157.     
  158.     If frame Is Nothing Then Exit Function
  159.         
  160.                         
  161.     Dim currentMatrix As D3DMATRIX
  162.     Dim NewWorldMatrix As D3DMATRIX
  163.     
  164.     currentMatrix = frame.GetMatrix
  165.         
  166.     'Setup our basis matrix for this frame
  167.     D3DXMatrixMultiply NewWorldMatrix, currentMatrix, world
  168.     
  169.     vIn.x = x:    vIn.y = y
  170.     
  171.     'Compute point on Near Clip plane at cursor
  172.     vIn.z = 0
  173.     D3DXVec3Unproject vNear, vIn, viewport, proj, view, NewWorldMatrix
  174.     
  175.     'compute point on far clip plane at cursor
  176.     vIn.z = 1
  177.     D3DXVec3Unproject vFar, vIn, viewport, proj, view, NewWorldMatrix
  178.  
  179.     'Comput direction vector
  180.     D3DXVec3Subtract vDir, vFar, vNear
  181.                 
  182.     
  183.     
  184.     Dim item As D3D_PICK_RECORD
  185.     
  186.     
  187.     'Check all child meshes
  188.     'Even if we got a hit we continue as the next mesh may be closer
  189.     Dim childMesh As CD3DMesh
  190.     For i = 0 To frame.GetChildMeshCount() - 1
  191.         
  192.         Set childMesh = frame.GetChildMesh(i)
  193.         
  194.         If Not childMesh Is Nothing Then
  195.             g_d3dx.Intersect childMesh.mesh, vNear, vDir, item.hit, item.triFaceid, item.a, item.b, item.dist, 0
  196.         End If
  197.         
  198.         If item.hit <> 0 Then
  199.             InternalAddItem frame, childMesh, item
  200.             item.hit = 0
  201.         End If
  202.         bHit = True
  203.     Next
  204.     
  205.     'check pick for all child frame
  206.     Dim childFrame As CD3DFrame
  207.     For i = 0 To frame.GetChildFrameCount() - 1
  208.         Set childFrame = frame.GetChildFrame(i)
  209.         bHit = bHit Or _
  210.                 ViewportPickEx(childFrame, viewport, proj, view, NewWorldMatrix, x, y)
  211.     Next
  212.  
  213.     ViewportPickEx = bHit
  214.  
  215. End Function
  216.  
  217.  
  218.  
  219. '-----------------------------------------------------------------------------
  220. ' Name: RayPick
  221. ' Desc: given a ray cast it into a scene graph
  222. ' Params:
  223. '    frame      parent of frame heirarchy to pick from
  224. '    vOrig      origen of the ray to cast
  225. '    vDir       direction of the ray
  226. '
  227. ' Note: the following functions will fail on PURE HAL devices
  228. '       use RayPickEx if working with pureHal devices
  229. '       Call getCount to see if the ray hit any objects
  230. '
  231. '-----------------------------------------------------------------------------
  232. Public Function RayPick(frame As CD3DFrame, vOrig As D3DVECTOR, vDir As D3DVECTOR)
  233.     Destroy
  234.         
  235.     Dim world As D3DMATRIX
  236.     
  237.     
  238.     g_dev.GetTransform D3DTS_WORLD, world
  239.     
  240.     RayPick = RayPickEx(frame, world, vOrig, vDir)
  241.     
  242. End Function
  243.  
  244. '-----------------------------------------------------------------------------
  245. ' Name: RayPickEx
  246. ' Desc: Aux function for RayPickEx
  247. '-----------------------------------------------------------------------------
  248. Public Function RayPickEx(frame As CD3DFrame, worldmatrix As D3DMATRIX, vOrig As D3DVECTOR, vDir As D3DVECTOR) As Boolean
  249.  
  250.     Dim NewWorldMatrix As D3DMATRIX     'world matrix for this stack frame
  251.     Dim InvWorldMatrix As D3DMATRIX     'world matrix for this stack frame
  252.     Dim currentMatrix As D3DMATRIX
  253.     Dim i As Long, det As Single, bHit As Boolean
  254.     Dim vNewDir As D3DVECTOR, vNewOrig As D3DVECTOR
  255.         
  256.     If frame Is Nothing Then Exit Function
  257.         
  258.     currentMatrix = frame.GetMatrix
  259.         
  260.     'Setup our basis matrix for this frame
  261.     D3DXMatrixMultiply NewWorldMatrix, currentMatrix, worldmatrix
  262.     D3DXMatrixInverse InvWorldMatrix, det, NewWorldMatrix
  263.     
  264.     
  265.     ' we want to compute vdir and vOrig in model space
  266.     ' note we use TransformNormal so we dont translate vDir
  267.     ' just rotate it into a new dir
  268.     Call D3DXVec3TransformNormal(vNewDir, vDir, InvWorldMatrix)
  269.     Call D3DXVec3TransformCoord(vNewOrig, vOrig, InvWorldMatrix)
  270.             
  271.                 
  272.     Dim item As D3D_PICK_RECORD
  273.     
  274.     
  275.     'Check all child meshes
  276.     'Even if we got a hit we continue as the next mesh may be closer
  277.     Dim childMesh As CD3DMesh
  278.     For i = 0 To frame.GetChildMeshCount() - 1
  279.         
  280.         Set childMesh = frame.GetChildMesh(i)
  281.         
  282.         If Not childMesh Is Nothing Then
  283.             Call D3DXVec3Scale(vDir, vDir, 1000) 'Workaround for d3dx Intersect bug
  284.             g_d3dx.Intersect childMesh.mesh, vNewOrig, vDir, item.hit, item.triFaceid, item.a, item.b, item.dist, 0
  285.         End If
  286.         
  287.         If item.hit <> 0 Then
  288.             InternalAddItem frame, childMesh, item
  289.             item.hit = 0
  290.         End If
  291.         bHit = True
  292.     Next
  293.     
  294.     'check pick for all child frame
  295.     Dim childFrame As CD3DFrame
  296.     For i = 0 To frame.GetChildFrameCount() - 1
  297.         Set childFrame = frame.GetChildFrame(i)
  298.         bHit = bHit Or _
  299.             RayPickEx(childFrame, NewWorldMatrix, vOrig, vDir)
  300.     Next
  301.  
  302.     RayPickEx = bHit
  303.  
  304. End Function
  305.  
  306.  
  307.  
  308.  
  309. '-----------------------------------------------------------------------------
  310. ' InternalAddItem
  311. '-----------------------------------------------------------------------------
  312. Private Sub InternalAddItem(parentFrame As CD3DFrame, mesh As CD3DMesh, item As D3D_PICK_RECORD)
  313.     Dim maxsize As Long
  314.     If m_maxsize = 0 Then
  315.         ReDim m_item(kGrowSize)
  316.         ReDim m_mesh(kGrowSize)
  317.         ReDim m_frame(kGrowSize)
  318.         m_maxsize = kGrowSize
  319.     ElseIf m_count >= m_maxsize Then
  320.         ReDim Preserve m_item(m_maxsize + kGrowSize)
  321.         ReDim Preserve m_frame(m_maxsize + kGrowSize)
  322.         ReDim Preserve m_mesh(m_maxsize + kGrowSize)
  323.         m_maxsize = m_maxsize + kGrowSize
  324.     End If
  325.     
  326.     Set m_mesh(m_count) = mesh
  327.     Set m_frame(m_count) = parentFrame
  328.     m_item(m_count) = item
  329.                              
  330.     m_count = m_count + 1
  331. End Sub
  332.  
  333.  
  334.  
  335.